package collection.set;

import org.junit.Test;

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

/*
* Set:存储无序的,不可重复的数据
*   HashSet:Set接口的主要实现类(可以存储null)
*       LinkHashSet:是HashSet的子类,遍历内部数据时,可以按照添加顺序去遍历
*
*   TreeSet:使用红黑树存储,放入的元素要是同一类型的对象,可以按照指定属性进行排序
*
*  要求:向set中添加的元素的类,必须重写equals()和hashCode()方法
*       重写的equals()和hashCode尽可能保持一致性:相等的对象必须具有相等的散列码
* */
public class SetTest {

    /*
     * 一:Set:
     *  存储无序的:不等于随机性,存储的数据在底层数组中并非按照数组索引顺序添加,而是根据数据的哈希值排序
     *
     *  不可重复:保证添加的元素按照equals()判断时,不能是true,相同的元素只能添加一个
     *
     * 二:添加顺序的过程:以HashSet为例:
     *      向HashSet中添加元素a
     *          1:调用元素a所在类的的hashcode()方法,计算a的哈希值
     *          2:接着对次哈希值通过某种算法计算出在hashSet底层数组中的存放位置,即索引位置,判断此位置上时候已经有元素:
     *              如果此位置没有其他元素,则添加成功
     *              如果此位置有其他元素,则比较两个元素的哈希值
     *                  如果hash值不同,则添加成功
     *                  如果hash只形同,进而调用所在类的equals()方法,
     *                      如果equals()返回true,添加失败
     *                      如果equals()返回false,添加成功
     *
     *          注:对于同一位置的元素,几个元素以链表形式存储
     *              JDK7头部插入
     *              JDK8尾部插入
     *
     * HashSet底层:数组加链表结构
     *
     * */
    @Test
    public void test1(){
        Set<Object> set = new HashSet<>();
        set.add(456);
        set.add(123);
        set.add(123);
        set.add("AA");
        set.add("aa");
        set.add(new User("xiaoli",18));
        set.add(new User("xiaoli",18));

        Iterator<Object> iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

    }

    /*
    * LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了两个指针,分别指向前一个和后一个元素,来保证添加到结合中的元素的顺序
    * */
    @Test
    public void test2(){
        Set set = new LinkedHashSet();
        set.add(456);
        set.add(123);
        set.add(123);
        set.add("AA");
        set.add("aa");
        set.add(new User("xiaoli",18));
        set.add(new User("xiaoli",18));

        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

    }
}
